package com.link4a.doms.web;

import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.condition.*;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;

/**
 * @author brown
 */
public final class SimpleRequestMapping extends RequestMappingHandlerMapping {

	private static final String CONTROLLER_SUFFIX = "Controller";

	@Override
	protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
		RequestMappingInfo info = null;
		RequestMapping methodAnnotation = AnnotationUtils.findAnnotation(method, RequestMapping.class);

		if (methodAnnotation != null) {
			String[] methodPatterns = resolveMethodPatterns(methodAnnotation, method);
			info = createRequestMappingInfo(methodAnnotation, methodPatterns);

			RequestMapping typeAnnotation = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
			String[] handlerPatterns = resolveHandlerPatterns(typeAnnotation, handlerType);
			info = createRequestMappingInfo(typeAnnotation, handlerPatterns).combine(info);
		}

		return info;
	}

	private String[] resolveMethodPatterns(RequestMapping annotation, Method method) {
		String[] patterns = annotation.value();
		if (patterns == null || patterns.length == 0) {
			patterns = new String[] { method.getName() };
		}
		return patterns;
	}

	private String[] resolveHandlerPatterns(RequestMapping annotation, Class<?> handlerType) {
		if (annotation != null) {
			return annotation.value();
		}
		String handlerName = handlerType.getSimpleName();
		String path = StringUtils.substringBefore(handlerName, CONTROLLER_SUFFIX);
		return new String[] { StringUtils.uncapitalize(path) };
	}

	private RequestMappingInfo createRequestMappingInfo(RequestMapping annotation, String[] patterns) {
		if (annotation == null) {
			return new RequestMappingInfo(new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(),
					useSuffixPatternMatch(), useTrailingSlashMatch(), getFileExtensions()), null, null, null, null,
					null, null);
		}
		return new RequestMappingInfo(new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(),
				useSuffixPatternMatch(), useTrailingSlashMatch(), getFileExtensions()),
				new RequestMethodsRequestCondition(annotation.method()),
				new ParamsRequestCondition(annotation.params()), new HeadersRequestCondition(annotation.headers()),
				new ConsumesRequestCondition(annotation.consumes(), annotation.headers()),
				new ProducesRequestCondition(annotation.produces(), annotation.headers(),
						getContentNegotiationManager()), null);
	}
}
